home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / phantz.arc / PHANT2.Z / PHANT2
Text File  |  1991-06-06  |  60KB  |  2,153 lines

  1.  
  2. : ---------CUT HERE---------
  3. : This is a shar archive.  Extract with sh, not csh.
  4. : The rest of this file will extract:
  5. :  phantglobs.h phantglobs.c fight.c convert.c
  6. echo x - phantglobs.h
  7. sed 's/^X//' > phantglobs.h << '!EOR!'
  8. X/*
  9. X * phantglobs.h - global declarations for Phantasia
  10. X */
  11. X
  12. Xextern    double    Circle;        /* which circle player is in            */
  13. Xextern    double    Shield;        /* force field thrown up in monster battle    */
  14. X
  15. Xextern    bool    Beyond;        /* set if player is beyond point of no return    */
  16. Xextern    bool    Marsh;        /* set if player is in dead marshes        */
  17. Xextern    bool    Throne;        /* set if player is on throne            */
  18. Xextern    bool    Changed;    /* set if important player stats have changed    */
  19. Xextern    bool    Wizard;        /* set if player is the 'wizard' of the game    */
  20. Xextern    bool    Timeout;    /* set if short timeout waiting for input    */
  21. Xextern    bool    Windows;    /* set if we are set up for curses stuff    */
  22. Xextern    bool    Luckout;    /* set if we have tried to luck out in fight    */
  23. Xextern    bool    Foestrikes;    /* set if foe gets a chance to hit in battleplayer()*/
  24. Xextern    bool    Echo;        /* set if echo input to terminal        */
  25. X
  26. Xextern    int    Users;        /* number of users currently playing        */
  27. Xextern    int    Whichmonster;    /* which monster we are fighting        */
  28. Xextern    int    Lines;        /* line on screen counter for fight routines    */
  29. X#ifdef OK_TO_PLAY
  30. Xextern    int    Okcount;    /* counter for checking ok_to_play        */
  31. X#endif
  32. X
  33. Xextern    jmp_buf Fightenv;    /* used to jump into fight routine        */
  34. Xextern    jmp_buf Timeoenv;    /* used for timing out waiting for input    */
  35. X
  36. Xextern    long    Fileloc;    /* location in file of player statistics    */
  37. X
  38. Xextern    char    *Login;        /* pointer to login of current player        */
  39. Xextern    char    *Enemyname;    /* pointer name of monster/player we are battling*/
  40. X
  41. Xextern    struct player    Player;    /* stats for player                */
  42. Xextern    struct player    Other;    /* stats for another player            */
  43. X
  44. Xextern    struct monster    Curmonster;/* stats for current monster            */
  45. X
  46. Xextern    struct energyvoid Enrgyvoid;/* energy void buffer            */
  47. X
  48. Xextern    struct charstats Stattable[];/* used for rolling and changing player stats*/
  49. X
  50. Xextern    struct charstats *Statptr;/* pointer into Stattable[]            */
  51. X
  52. Xextern    struct menuitem    Menu[];    /* menu of items for purchase            */
  53. X
  54. Xextern    FILE    *Playersfp;    /* pointer to open player file            */
  55. Xextern    FILE    *Monstfp;    /* pointer to open monster file            */
  56. Xextern    FILE    *Messagefp;    /* pointer to open message file            */
  57. Xextern    FILE    *Energyvoidfp;    /* pointer to open energy void file        */
  58. X
  59. Xextern    char    Databuf[];    /* a place to read data into            */
  60. X
  61. X/* edit these path definitions to let files reside elsewhere */
  62. Xextern    char    Monstfile[];    /* monster database        */
  63. Xextern    char    Peoplefile[];    /* player database        */
  64. Xextern    char    Gameprog[];    /* game binary            */
  65. Xextern    char    Messfile[];    /* player to player messages    */
  66. Xextern    char    Lastdead[];    /* data on last player killed    */
  67. Xextern    char    Helpfile[];    /* manual pages            */
  68. Xextern    char    Motdfile[];    /* message from 'wizard'    */
  69. Xextern    char    Goldfile[];    /* gold collected in taxes    */
  70. Xextern    char    Voidfile[];    /* energy void database        */
  71. Xextern    char    Scorefile[];    /* hi score database        */
  72. X#ifdef ENEMY
  73. Xextern    char    Enemyfile[];    /* restricted account database    */
  74. X#endif
  75. X
  76. X/* some canned strings for messages */
  77. Xextern    char    Illcmd[];
  78. Xextern    char    Illmove[];
  79. Xextern    char    Illspell[];
  80. Xextern    char    Nomana[];
  81. Xextern    char    Somebetter[];
  82. Xextern    char    Nobetter[];
  83. X
  84. X/* library functions and system calls */
  85. Xextern    long    time();
  86. Xextern    char    *getlogin();
  87. Xextern    char    *getpass();
  88. Xextern    char    *strchr();
  89. Xextern    char    *strcat();
  90. Xextern    char    *strcpy();
  91. Xextern    char    *strncpy();
  92. Xextern    char    *getenv();
  93. Xstruct    passwd    *getpwuid();
  94. Xextern    char    *fgets();
  95. X
  96. X/* functions which we need to know about */
  97. Xextern    int    interrupt();
  98. Xextern    int    ill_sig();
  99. Xextern    int    catchalarm();
  100. Xextern    long    recallplayer();
  101. Xextern    long    findname();
  102. Xextern    long    allocrecord();
  103. Xextern    long    rollnewplayer();
  104. Xextern    long    allocvoid();
  105. Xextern    double    random();
  106. Xextern    double    distance();
  107. Xextern    double    infloat();
  108. Xextern    double    explevel();
  109. Xextern    char    *descrlocation();
  110. Xextern    char    *descrtype();
  111. Xextern    char    *descrstatus();
  112. !EOR!
  113. echo x - phantglobs.c
  114. sed 's/^X//' > phantglobs.c << '!EOR!'
  115. X/*
  116. X * phantglobs.c - globals for Phantasia
  117. X */
  118. X
  119. X#include "include.h"
  120. X
  121. Xdouble    Circle;        /* which circle player is in            */
  122. Xdouble    Shield;        /* force field thrown up in monster battle    */
  123. X
  124. Xbool    Beyond;        /* set if player is beyond point of no return    */
  125. Xbool    Marsh;        /* set if player is in dead marshes        */
  126. Xbool    Throne;        /* set if player is on throne            */
  127. Xbool    Changed;    /* set if important player stats have changed    */
  128. Xbool    Wizard;        /* set if player is the 'wizard' of the game    */
  129. Xbool    Timeout;    /* set if short timeout waiting for input    */
  130. Xbool    Windows;    /* set if we are set up for curses stuff    */
  131. Xbool    Luckout;    /* set if we have tried to luck out in fight    */
  132. Xbool    Foestrikes;    /* set if foe gets a chance to hit in battleplayer()    */
  133. Xbool    Echo;        /* set if echo input to terminal        */
  134. X
  135. Xint    Users;        /* number of users currently playing        */
  136. Xint    Whichmonster;    /* which monster we are fighting        */
  137. Xint    Lines;        /* line on screen counter for fight routines    */
  138. X#ifdef OK_TO_PLAY
  139. Xint    Okcount;    /* counter for checking ok_to_play        */
  140. X#endif
  141. X
  142. Xjmp_buf Fightenv;    /* used to jump into fight routine        */
  143. Xjmp_buf Timeoenv;    /* used for timing out waiting for input    */
  144. X
  145. Xlong    Fileloc;    /* location in file of player statistics    */
  146. X
  147. Xchar    *Login;        /* pointer to login of player            */
  148. Xchar    *Enemyname;    /* pointer name of monster/player we are battling*/
  149. X
  150. Xstruct    player    Player;    /* stats for player                */
  151. Xstruct    player    Other;    /* stats for another player            */
  152. X
  153. Xstruct    monster    Curmonster;/* stats for current monster            */
  154. X
  155. Xstruct    energyvoid Enrgyvoid;/* energy void buffer            */
  156. X
  157. Xstruct    charstats *Statptr;/* pointer into Stattable[]            */
  158. X
  159. X/* lookup table for character type dependent statistics */
  160. Xstruct    charstats Stattable[7] =
  161. X    {
  162. X    /* MAGIC USER */
  163. X    /* max brains, max mana, weakness, gold tote, ring duration */
  164. X    15.0, 200.0, 18.0, 175.0, 10,
  165. X    /* quickness strength     mana         energy       brains       magic lvl */
  166. X    30, 6, 0.0,  10, 6, 2.0,  50,51,75.0,  30,16,20.0,  60,26, 6.0,     5, 5,2.75,
  167. X
  168. X    /* FIGHTER */
  169. X    /* max brains, max mana, weakness, gold tote, ring duration */
  170. X    10.0, 110.0, 15.0, 220.0, 20,
  171. X    /* quickness strength     mana         energy       brains       magic lvl */
  172. X    30, 6, 0.0,  40,16, 3.0,  30,21,40.0,  45,26,30.0,  25,21, 3.0,     3, 4, 1.5,
  173. X
  174. X    /* ELF */
  175. X    /* max brains, max mana, weakness, gold tote, ring duration */
  176. X    12.0, 150.0, 17.0, 190.0, 13,
  177. X    /* quickness strength     mana         energy       brains       magic lvl */
  178. X    32, 7, 0.0,  35,11, 2.5,  45,46,65.0,  30,21,25.0,  40,26, 4.0,     4, 4, 2.0,
  179. X
  180. X    /* DWARF */
  181. X    /* max brains, max mana, weakness, gold tote, ring duration */
  182. X    7.0, 80.0, 13.0, 255.0,  25,
  183. X    /* quickness strength     mana         energy       brains       magic lvl */
  184. X    25, 6, 0.0,  50,21, 5.0,  25,21,30.0,  60,41,35.0,  20,21, 2.5,     2, 4, 1.0,
  185. X
  186. X    /* HALFLING */
  187. X    /* max brains, max mana, weakness, gold tote, ring duration */
  188. X    11.0, 80.0, 10.0, 125.0, 40,
  189. X    /* quickness strength     mana         energy       brains       magic lvl */
  190. X    34, 0, 0.0,  20, 6, 2.0,  25,21,30.0,  55,36,30.0,  40,36, 4.5,     1, 4, 1.0,
  191. X
  192. X    /* EXPERIMENTO */
  193. X    /* max brains, max mana, weakness, gold tote, ring duration */
  194. X    9.0, 90.0, 16.0, 160.0, 20,
  195. X    /* quickness strength     mana         energy       brains       magic lvl */
  196. X    27, 0, 0.0,  25, 0, 0.0,  100,0, 0.0,  35, 0, 0.0,  25, 0, 0.0,     2, 0, 0.0,
  197. X
  198. X    /* SUPER */
  199. X    /* max brains, max mana, weakness, gold tote, ring duration */
  200. X    15.0, 200.0, 10.0, 225.0, 40,
  201. X    /* quickness strength     mana         energy       brains       magic lvl */
  202. X    38, 0, 0.0,  65, 0, 5.0,  100,0,75.0,  80, 0,35.0,  85, 0, 6.0,     9, 0,2.75
  203. X    };
  204. X
  205. X/* menu of items for purchase */
  206. Xstruct menuitem    Menu[] =
  207. X    {
  208. X    "Mana", 1,
  209. X    "Shield", 5,
  210. X    "Book", 200,
  211. X    "Sword", 500,
  212. X    "Charm", 1000,
  213. X    "Quicksilver", 2500,
  214. X    "Blessing", 1000,
  215. X    };
  216. X
  217. XFILE    *Playersfp;    /* pointer to open player file            */
  218. XFILE    *Monstfp;    /* pointer to open monster file            */
  219. XFILE    *Messagefp;    /* pointer to open message file            */
  220. XFILE    *Energyvoidfp;    /* pointer to open energy void file        */
  221. X
  222. Xchar    Databuf[SZ_DATABUF];    /* a place to read data into        */
  223. X
  224. X/* edit these path definitions to let files reside elsewhere */
  225. Xchar    Monstfile[] = DEST/monsters";    /* monster database        */
  226. Xchar    Peoplefile[] = DEST/characs";    /* player database        */
  227. Xchar    Gameprog[] = DEST/phantasia";    /* game binary            */
  228. Xchar    Messfile[] = DEST/mess";    /* player to player messages    */
  229. Xchar    Lastdead[] = DEST/lastdead";    /* data on last player killed    */
  230. Xchar    Helpfile[] = DEST/phant.help";    /* manual pages            */
  231. Xchar    Motdfile[] = DEST/motd";    /* message from 'wizard'    */
  232. Xchar    Goldfile[] = DEST/gold";    /* gold collected in taxes    */
  233. Xchar    Voidfile[] = DEST/void";    /* energy void database        */
  234. Xchar    Scorefile[] = DEST/scoreboard";    /* hi score database        */
  235. X#ifdef ENEMY
  236. Xchar    Enemyfile[] = DEST/enemy";    /* restricted account database    */
  237. X#endif
  238. X
  239. X/* some canned strings for messages */
  240. Xchar    Illcmd[] = "Illegal command.\n";
  241. Xchar    Illmove[] = "Too far.\n";
  242. Xchar    Illspell[] = "Illegal spell.\n";
  243. Xchar    Nomana[] = "Not enought mana for that spell.\n";
  244. Xchar    Somebetter[] = "But you already have something better.\n";
  245. Xchar    Nobetter[] = "That's no better than what you already have.\n";
  246. !EOR!
  247. echo x - fight.c
  248. sed 's/^X//' > fight.c << '!EOR!'
  249. X/*
  250. X * fight.c   Phantasia monster fighting routines
  251. X */
  252. X
  253. X#include "include.h"
  254. X
  255. X/************************************************************************
  256. X/
  257. X/ FUNCTION NAME: encounter()
  258. X/
  259. X/ FUNCTION: monster battle routine
  260. X/
  261. X/ AUTHOR: E. A. Estes, 2/20/86
  262. X/
  263. X/ ARGUMENTS:
  264. X/    int particular - particular monster to fight if >= 0
  265. X/
  266. X/ RETURN VALUE: none
  267. X/
  268. X/ MODULES CALLED: monsthits(), playerhits(), readmessage(), callmonster(), 
  269. X/    writerecord(), pickmonster(), displaystats(), pow(), cancelmonster(), 
  270. X/    awardtreasure(), more(), death(), wmove(), setjmp(), random(), printw(), 
  271. X/    longjmp(), wrefresh(), mvprintw(), wclrtobot()
  272. X/
  273. X/ GLOBAL INPUTS: Curmonster, Whichmonster, LINES, Lines, Circle, Shield, 
  274. X/    Player, *stdscr, Fileloc, Fightenv[], *Enemyname
  275. X/
  276. X/ GLOBAL OUTPUTS: Curmonster, Whichmonster, Lines, Shield, Player, Luckout
  277. X/
  278. X/ DESCRIPTION:
  279. X/    Choose a monster and check against some special types.
  280. X/    Arbitrate between monster and player.  Watch for either
  281. X/    dying.
  282. X/
  283. X/************************************************************************/
  284. X
  285. Xencounter(particular)
  286. Xint    particular;
  287. X{
  288. Xbool    firsthit = Player.p_blessing;    /* set if player gets the first hit */
  289. Xint    howmany = 1;            /* how many time flocked */
  290. X
  291. X    /* let others know what we are doing */
  292. X    Player.p_status = S_MONSTER;
  293. X    writerecord(&Player, Fileloc);
  294. X
  295. X#ifdef SYS5
  296. X    flushinp();
  297. X#endif
  298. X
  299. X    Shield = 0.0;        /* no shield up yet */
  300. X
  301. X    if (particular >= 0)
  302. X    /* monster is specified */
  303. X    Whichmonster = particular;
  304. X    else
  305. X    /* pick random monster */
  306. X    Whichmonster = pickmonster();
  307. X
  308. X    setjmp(Fightenv);        /* this is to enable changing fight state */
  309. X
  310. X    move(6, 0);
  311. X    clrtobot();            /* clear bottom area of screen */
  312. X
  313. X    Lines = 9;
  314. X    callmonster(Whichmonster);    /* set up monster to fight */
  315. X
  316. X    Luckout = FALSE;        /* haven't tried to luckout yet */
  317. X
  318. X    if (Curmonster.m_type == SM_MORGOTH)
  319. X    mvprintw(4, 0, "You've encountered %s, Bane of the Council and Valar.\n",
  320. X        Enemyname);
  321. X
  322. X    if (Curmonster.m_type == SM_UNICORN)
  323. X    {
  324. X    if (Player.p_virgin)
  325. X        {
  326. X        printw("You just subdued %s, thanks to the virgin.\n", Enemyname);
  327. X        Player.p_virgin = FALSE;
  328. X        }
  329. X    else
  330. X        {
  331. X        printw("You just saw %s running away!\n", Enemyname);
  332. X        Curmonster.m_experience = 0.0;
  333. X        Curmonster.m_treasuretype = 0;
  334. X        }
  335. X    }
  336. X    else
  337. X    /* not a special monster */
  338. X    for (;;)
  339. X        /* print header, and arbitrate between player and monster */
  340. X        {
  341. X        mvprintw(6, 0, "You are being attacked by %s,   EXP: %.0f   (Size: %.0f)\n",
  342. X        Enemyname, Curmonster.m_experience, Circle);
  343. X
  344. X        displaystats();
  345. X        mvprintw(1, 26, "%20.0f", Player.p_energy + Shield);    /* overprint energy */
  346. X        readmessage();
  347. X
  348. X        if (Curmonster.m_type == SM_DARKLORD
  349. X        && Player.p_blessing
  350. X        && Player.p_charms > 0)
  351. X        /* overpower Dark Lord with blessing and charm */
  352. X        {
  353. X        mvprintw(7, 0, "You just overpowered %s!", Enemyname);
  354. X        Lines = 8;
  355. X        Player.p_blessing = FALSE;
  356. X        --Player.p_charms;
  357. X        break;
  358. X        }
  359. X
  360. X        /* allow paralyzed monster to wake up */
  361. X        Curmonster.m_speed = MIN(Curmonster.m_speed + 1.0, Curmonster.m_maxspeed);
  362. X
  363. X        if (random() * Curmonster.m_speed > random() * Player.p_speed
  364. X        /* monster is faster */
  365. X        && Curmonster.m_type != SM_DARKLORD
  366. X        /* not D. L. */
  367. X        && Curmonster.m_type != SM_SHRIEKER
  368. X        /* not mimic */
  369. X        && !firsthit)
  370. X        /* monster gets a hit */
  371. X        monsthits();
  372. X        else
  373. X        /* player gets a hit */
  374. X        {
  375. X        firsthit = FALSE;
  376. X        playerhits();
  377. X        }
  378. X
  379. X        refresh();
  380. X
  381. X        if (Lines > LINES - 2)
  382. X        /* near bottom of screen - pause */
  383. X        {
  384. X        more(Lines);
  385. X        move(Lines = 8, 0);
  386. X        clrtobot();
  387. X        }
  388. X
  389. X        if (Player.p_energy <= 0.0)
  390. X        /* player died */
  391. X        {
  392. X        more(Lines);
  393. X        death(Enemyname);
  394. X        cancelmonster();
  395. X        break;        /* fight ends if the player is saved from death */
  396. X        }
  397. X
  398. X        if (Curmonster.m_energy <= 0.0)
  399. X        /* monster died */
  400. X        break;
  401. X        }
  402. X
  403. X    /* give player credit for killing monster */
  404. X    Player.p_experience += Curmonster.m_experience;
  405. X
  406. X    if (random() < Curmonster.m_flock / 100.0)
  407. X    /* monster flocks */
  408. X    {
  409. X    more(Lines);
  410. X    ++howmany;
  411. X    longjmp(Fightenv, 0);
  412. X    /*NOTREACHED*/
  413. X    }
  414. X    else if (Circle > 1.0
  415. X    && Curmonster.m_treasuretype > 0
  416. X    && random() > 0.2 + pow(0.4, (double) (howmany / 3 + Circle / 3.0)))
  417. X    /* monster has treasure; this takes # of flocks and size into account */
  418. X    {
  419. X    more(Lines);
  420. X    awardtreasure();
  421. X    }
  422. X
  423. X    /* pause before returning */
  424. X    getyx(stdscr, Lines, howmany);
  425. X    more(Lines + 1);
  426. X
  427. X    Player.p_ring.ring_inuse = FALSE;    /* not using ring */
  428. X
  429. X    /* clean up the screen */
  430. X    move(4, 0);
  431. X    clrtobot();
  432. X}
  433. X/* */
  434. X/************************************************************************
  435. X/
  436. X/ FUNCTION NAME: pickmonster()
  437. X/
  438. X/ FUNCTION: choose a monster based upon where we are
  439. X/
  440. X/ AUTHOR: E. A. Estes, 2/20/86
  441. X/
  442. X/ ARGUMENTS: none
  443. X/
  444. X/ RETURN VALUE: monster number to call
  445. X/
  446. X/ MODULES CALLED: floor(), random()
  447. X/
  448. X/ GLOBAL INPUTS: Marsh, Circle, Player
  449. X/
  450. X/ GLOBAL OUTPUTS: none
  451. X/
  452. X/ DESCRIPTION:
  453. X/    Certain monsters can be found in certain areas of the grid.
  454. X/    We take care of rolling them here.
  455. X/    Unfortunately, this routine assumes that the monster data
  456. X/    base is arranged in a particular order.  If the data base
  457. X/    is altered (to add monsters, or make them tougher), this
  458. X/    routine may also need to be changed.
  459. X/
  460. X/************************************************************************/
  461. X
  462. Xpickmonster()
  463. X{
  464. X    if (Player.p_specialtype == SC_VALAR)
  465. X    /* even chance of any monster */
  466. X    return((int) ROLL(0.0, 100.0));
  467. X
  468. X    if (Marsh)
  469. X    /* water monsters */
  470. X    return((int) ROLL(0.0, 15.0));
  471. X
  472. X    else if (Circle > 24)
  473. X    /* even chance of all non-water monsters */
  474. X    return((int) ROLL(14.0, 86.0));
  475. X
  476. X    else if (Circle > 15)
  477. X    /* chance of all non-water monsters, weighted toward middle */
  478. X    return((int) (ROLL(0.0, 50.0) + ROLL(14.0, 37.0)));
  479. X
  480. X    else if (Circle > 8)
  481. X    /* not all non-water monsters, weighted toward middle */
  482. X    return((int) (ROLL(0.0, 50.0) + ROLL(14.0, 26.0)));
  483. X
  484. X    else if (Circle > 3)
  485. X    /* even chance of some tamer non-water monsters */
  486. X    return((int) ROLL(14.0, 50.0));
  487. X
  488. X    else 
  489. X    /* even chance of some of the tamest non-water monsters */
  490. X    return((int) ROLL(14.0, 25.0));
  491. X}
  492. X/* */
  493. X/************************************************************************
  494. X/
  495. X/ FUNCTION NAME: playerhits()
  496. X/
  497. X/ FUNCTION: prompt player for action in monster battle, and process
  498. X/
  499. X/ AUTHOR: E. A. Estes, 12/4/85
  500. X/
  501. X/ ARGUMENTS: none
  502. X/
  503. X/ RETURN VALUE: none
  504. X/
  505. X/ MODULES CALLED: hitmonster(), throwspell(), inputoption(), cancelmonster(), 
  506. X/    floor(), wmove(), random(), altercoordinates(), waddstr(), mvprintw(), 
  507. X/    wclrtoeol(), wclrtobot()
  508. X/
  509. X/ GLOBAL INPUTS: Curmonster, Lines, Player, *stdscr, Luckout, *Enemyname
  510. X/
  511. X/ GLOBAL OUTPUTS: Curmonster, Lines, Player, Luckout
  512. X/
  513. X/ DESCRIPTION:
  514. X/    Process all monster battle options.
  515. X/
  516. X/************************************************************************/
  517. X
  518. Xplayerhits()
  519. X{
  520. Xdouble    inflict;    /* damage inflicted */
  521. Xint    ch;        /* input */
  522. X
  523. X    mvaddstr(7, 0, "1:Melee  2:Skirmish  3:Evade  4:Spell  5:Nick  ");
  524. X
  525. X    if (!Luckout)
  526. X    /* haven't tried to luckout yet */
  527. X    if (Curmonster.m_type == SM_MORGOTH)
  528. X        /* cannot luckout against Morgoth */
  529. X        addstr("6:Ally  ");
  530. X    else
  531. X        addstr("6:Luckout  ");
  532. X
  533. X    if (Player.p_ring.ring_type != R_NONE)
  534. X    /* player has a ring */
  535. X    addstr("7:Use Ring  ");
  536. X    else
  537. X    clrtoeol();
  538. X
  539. X    ch = inputoption();
  540. X
  541. X    move(8, 0);
  542. X    clrtobot();            /* clear any messages from before */
  543. X    Lines = 9;
  544. X    mvaddstr(4, 0, "\n\n");    /* clear status area */
  545. X
  546. X    switch (ch)
  547. X    {
  548. X    case 'T':        /* timeout; lose turn */
  549. X        break;
  550. X
  551. X    case ' ':
  552. X    case '1':        /* melee */
  553. X        /* melee affects monster's energy and strength */
  554. X        inflict = ROLL(Player.p_might / 2.0 + 5.0, 1.3 * Player.p_might)
  555. X        + (Player.p_ring.ring_inuse ? Player.p_might : 0.0);
  556. X
  557. X        Curmonster.m_melee += inflict;
  558. X        Curmonster.m_strength = Curmonster.m_o_strength
  559. X        - Curmonster.m_melee / Curmonster.m_o_energy
  560. X        * Curmonster.m_o_strength / 4.0;
  561. X        hitmonster(inflict);
  562. X        break;
  563. X
  564. X    case '2':        /* skirmish */
  565. X        /* skirmish affects monter's energy and speed */
  566. X        inflict = ROLL(Player.p_might / 3.0 + 3.0, 1.1 * Player.p_might)
  567. X        + (Player.p_ring.ring_inuse ? Player.p_might : 0.0);
  568. X
  569. X        Curmonster.m_skirmish += inflict;
  570. X        Curmonster.m_maxspeed = Curmonster.m_o_speed
  571. X        - Curmonster.m_skirmish / Curmonster.m_o_energy
  572. X        * Curmonster.m_o_speed / 4.0;
  573. X        hitmonster(inflict);
  574. X        break;
  575. X
  576. X    case '3':        /* evade */
  577. X        /* use brains and speed to try to evade */
  578. X        if ((Curmonster.m_type == SM_DARKLORD
  579. X        || Curmonster.m_type == SM_SHRIEKER
  580. X        /* can always run from D. L. and shrieker */
  581. X        || random() * Player.p_speed * Player.p_brains
  582. X            > random() * Curmonster.m_speed * Curmonster.m_brains)
  583. X        && (Curmonster.m_type != SM_MIMIC))
  584. X        /* cannot run from mimic */
  585. X        {
  586. X        mvaddstr(Lines++, 0, "You got away!");
  587. X        cancelmonster();
  588. X        altercoordinates(0.0, 0.0, A_NEAR);
  589. X        }
  590. X        else
  591. X        mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
  592. X
  593. X        break;
  594. X
  595. X    case 'M':
  596. X    case '4':        /* magic spell */
  597. X        throwspell();
  598. X        break;
  599. X
  600. X    case '5':        /* nick */
  601. X        /* hit 1 plus sword; give some experience */
  602. X        inflict = 1.0 + Player.p_sword;
  603. X        Player.p_experience += floor(Curmonster.m_experience / 10.0);
  604. X        Curmonster.m_experience *= 0.92;
  605. X        /* monster gets meaner */
  606. X        Curmonster.m_maxspeed += 2.0;
  607. X        Curmonster.m_speed = (Curmonster.m_speed < 0.0) ? 0.0 : Curmonster.m_speed + 2.0;
  608. X        if (Curmonster.m_type == SM_DARKLORD)
  609. X        /* Dark Lord; doesn't like to be nicked */
  610. X        {
  611. X        mvprintw(Lines++, 0,
  612. X            "You hit %s %.0f times, and made him mad!", Enemyname, inflict);
  613. X        Player.p_quickness /= 2.0;
  614. X        altercoordinates(0.0, 0.0, A_FAR);
  615. X        cancelmonster();
  616. X        }
  617. X        else
  618. X        hitmonster(inflict);
  619. X        break;
  620. X
  621. X    case 'B':
  622. X    case '6':    /* luckout */
  623. X        if (Luckout)
  624. X        mvaddstr(Lines++, 0, "You already tried that.");
  625. X        else
  626. X        {
  627. X        Luckout = TRUE;
  628. X        if (Curmonster.m_type == SM_MORGOTH)
  629. X            /* Morgoth; ally */
  630. X            {
  631. X            if (random() < Player.p_sin / 100.0)
  632. X            {
  633. X            mvprintw(Lines++, 0, "%s accepted!", Enemyname);
  634. X            cancelmonster();
  635. X            }
  636. X            else
  637. X            mvaddstr(Lines++, 0, "Nope, he's not interested.");
  638. X            }
  639. X        else
  640. X            /* normal monster; use brains for success */
  641. X            {
  642. X            if ((random() + 0.333) * Player.p_brains
  643. X            < (random() + 0.333) * Curmonster.m_brains)
  644. X            mvprintw(Lines++, 0, "You blew it, %s.", Player.p_name);
  645. X            else
  646. X            {
  647. X            mvaddstr(Lines++, 0, "You made it!");
  648. X            Curmonster.m_energy = 0.0;
  649. X            }
  650. X            }
  651. X        }
  652. X        break;
  653. X
  654. X    case '7':        /* use ring */
  655. X        if (Player.p_ring.ring_type != R_NONE)
  656. X        {
  657. X        mvaddstr(Lines++, 0, "Now using ring.");
  658. X        Player.p_ring.ring_inuse = TRUE;
  659. X        if (Player.p_ring.ring_type != R_DLREG)
  660. X            /* age ring */
  661. X            --Player.p_ring.ring_duration;
  662. X        }
  663. X        break;
  664. X    }
  665. X
  666. X}
  667. X/* */
  668. X/************************************************************************
  669. X/
  670. X/ FUNCTION NAME: monsthits()
  671. X/
  672. X/ FUNCTION: process a monster hitting the player
  673. X/
  674. X/ AUTHOR: E. A. Estes, 12/4/85
  675. X/
  676. X/ ARGUMENTS: none
  677. X/
  678. X/ RETURN VALUE: none
  679. X/
  680. X/ MODULES CALLED: cancelmonster(), scramblestats(), more(), floor(), wmove(), 
  681. X/    random(), altercoordinates(), longjmp(), waddstr(), mvprintw(), 
  682. X/    getanswer()
  683. X/
  684. X/ GLOBAL INPUTS: Curmonster, Lines, Circle, Shield, Player, *stdscr, 
  685. X/    Fightenv[], *Enemyname
  686. X/
  687. X/ GLOBAL OUTPUTS: Curmonster, Whichmonster, Lines, Shield, Player, 
  688. X/    *Enemyname
  689. X/
  690. X/ DESCRIPTION:
  691. X/    Handle all special monsters here.  If the monster is not a special
  692. X/    one, simply roll a hit against the player.
  693. X/
  694. X/************************************************************************/
  695. X
  696. Xmonsthits()
  697. X{
  698. Xdouble    inflict;        /* damage inflicted */
  699. Xint    ch;            /* input */
  700. X
  701. X    switch (Curmonster.m_type)
  702. X    /* may be a special monster */
  703. X    {
  704. X    case SM_DARKLORD:
  705. X        /* hits just enough to kill player */
  706. X        inflict = (Player.p_energy + Shield) * 1.02;
  707. X        goto SPECIALHIT;
  708. X
  709. X    case SM_SHRIEKER:
  710. X        /* call a big monster */
  711. X        mvaddstr(Lines++, 0,
  712. X        "Shrieeeek!!  You scared it, and it called one of its friends.");
  713. X        more(Lines);
  714. X        Whichmonster = (int) ROLL(70.0, 30.0);
  715. X        longjmp(Fightenv, 0);
  716. X        /*NOTREACHED*/
  717. X
  718. X    case SM_BALROG:
  719. X        /* take experience away */
  720. X        inflict = ROLL(10.0, Curmonster.m_strength);
  721. X        inflict = MIN(Player.p_experience, inflict);
  722. X        mvprintw(Lines++, 0, 
  723. X        "%s took away %.0f experience points.", Enemyname, inflict);
  724. X        Player.p_experience -= inflict;
  725. X        return;
  726. X
  727. X    case SM_FAERIES:
  728. X        if (Player.p_holywater > 0)
  729. X        /* holy water kills when monster tries to hit */
  730. X        {
  731. X        mvprintw(Lines++, 0, "Your holy water killed it!");
  732. X        --Player.p_holywater;
  733. X        Curmonster.m_energy = 0.0;
  734. X        return;
  735. X        }
  736. X        break;
  737. X
  738. X    case SM_NONE:
  739. X        /* normal hit */
  740. X        break;
  741. X
  742. X    default:
  743. X        if (random() > 0.2)
  744. X        /* normal hit */
  745. X        break;
  746. X
  747. X        /* else special things */
  748. X        switch (Curmonster.m_type)
  749. X        {
  750. X        case SM_LEANAN:
  751. X            /* takes some of the player's strength */
  752. X            inflict = ROLL(1.0, (Circle - 1.0) / 2.0);
  753. X            inflict = MIN(Player.p_strength, inflict);
  754. X            mvprintw(Lines++, 0, "%s sapped %0.f of your strength!",
  755. X            Enemyname, inflict);
  756. X            Player.p_strength -= inflict;
  757. X            Player.p_might -= inflict;
  758. X            break;
  759. X
  760. X        case SM_SARUMAN:
  761. X            if (Player.p_palantir)
  762. X            /* take away palantir */
  763. X            {
  764. X            mvprintw(Lines++, 0, "Wormtongue stole your palantir!");
  765. X            Player.p_palantir = FALSE;
  766. X            }
  767. X            else if (random() > 0.5)
  768. X            /* gems turn to gold */
  769. X            {
  770. X            mvprintw(Lines++, 0,
  771. X                "%s transformed your gems into gold!", Enemyname);
  772. X            Player.p_gold += Player.p_gems;
  773. X            Player.p_gems = 0.0;
  774. X            }
  775. X            else
  776. X            /* scramble some stats */
  777. X            {
  778. X            mvprintw(Lines++, 0, "%s scrambled your stats!", Enemyname);
  779. X            scramblestats();
  780. X            }
  781. X            break;
  782. X
  783. X        case SM_THAUMATURG:
  784. X            /* transport player */
  785. X            mvprintw(Lines++, 0, "%s transported you!", Enemyname);
  786. X            altercoordinates(0.0, 0.0, A_FAR);
  787. X            cancelmonster();
  788. X            break;
  789. X
  790. X        case SM_VORTEX:
  791. X            /* suck up some mana */
  792. X            inflict = ROLL(0, 7.5 * Circle);
  793. X            inflict = MIN(Player.p_mana, floor(inflict));
  794. X            mvprintw(Lines++, 0,
  795. X            "%s sucked up %.0f of your mana!", Enemyname, inflict);
  796. X            Player.p_mana -= inflict;
  797. X            break;
  798. X
  799. X        case SM_NAZGUL:
  800. X            /* try to take ring if player has one */
  801. X            if (Player.p_ring.ring_type != R_NONE)
  802. X            /* player has a ring */
  803. X            {
  804. X            mvaddstr(Lines++, 0, "Will you relinguish your ring ? ");
  805. X            ch = getanswer("YN", FALSE);
  806. X            if (ch == 'Y')
  807. X                /* take ring away */
  808. X                {
  809. X                Player.p_ring.ring_type = R_NONE;
  810. X                Player.p_ring.ring_inuse = FALSE;
  811. X                cancelmonster();
  812. X                break;
  813. X                }
  814. X            }
  815. X
  816. X            /* otherwise, take some brains */
  817. X            mvprintw(Lines++, 0,
  818. X            "%s neutralized 1/5 of your brain!", Enemyname);
  819. X            Player.p_brains *= 0.8;
  820. X            break;
  821. X
  822. X        case SM_TIAMAT:
  823. X            /* take some gold and gems */
  824. X            mvprintw(Lines++, 0,
  825. X            "%s took half your gold and gems and flew off.", Enemyname);
  826. X            Player.p_gold /= 2.0;
  827. X            Player.p_gems /= 2.0;
  828. X            cancelmonster();
  829. X            break;
  830. X
  831. X        case SM_KOBOLD:
  832. X            /* steal a gold piece and run */
  833. X            mvprintw(Lines++, 0,
  834. X            "%s stole one gold piece and ran away.", Enemyname);
  835. X            Player.p_gold = MAX(0.0, Player.p_gold - 1.0);
  836. X            cancelmonster();
  837. X            break;
  838. X
  839. X        case SM_SHELOB:
  840. X            /* bite and (medium) poison */
  841. X            mvprintw(Lines++, 0,
  842. X            "%s has bitten and poisoned you!", Enemyname);
  843. X            Player.p_poison -= 1.0;
  844. X            break;
  845. X
  846. X        case SM_LAMPREY:
  847. X            /*  bite and (small) poison */
  848. X            mvprintw(Lines++, 0, "%s bit and poisoned you!", Enemyname);
  849. X            Player.p_poison += 0.25;
  850. X            break;
  851. X
  852. X        case SM_BONNACON:
  853. X            /* fart and run */
  854. X            mvprintw(Lines++, 0, "%s farted and scampered off.", Enemyname);
  855. X            Player.p_energy /= 2.0;        /* damage from fumes */
  856. X            cancelmonster();
  857. X            break;
  858. X
  859. X        case SM_SMEAGOL:
  860. X            if (Player.p_ring.ring_type != R_NONE)
  861. X            /* try to steal ring */
  862. X            {
  863. X            mvprintw(Lines++, 0,
  864. X                "%s tried to steal your ring, ", Enemyname);
  865. X            if (random() > 0.1)
  866. X                addstr("but was unsuccessful.");
  867. X            else
  868. X                {
  869. X                addstr("and ran away with it!");
  870. X                Player.p_ring.ring_type = R_NONE;
  871. X                cancelmonster();
  872. X                }
  873. X            }
  874. X            break;
  875. X
  876. X        case SM_SUCCUBUS:
  877. X            /* inflict damage through shield */
  878. X            inflict = ROLL(15.0, Circle * 10.0);
  879. X            inflict = MIN(inflict, Player.p_energy);
  880. X            mvprintw(Lines++, 0, "%s sapped %.0f of your energy.",
  881. X            Enemyname, inflict);
  882. X            Player.p_energy -= inflict;
  883. X            break;
  884. X
  885. X        case SM_CERBERUS:
  886. X            /* take all metal treasures */
  887. X            mvprintw(Lines++, 0,
  888. X            "%s took all your metal treasures!", Enemyname);
  889. X            Player.p_crowns = 0;
  890. X            Player.p_sword =
  891. X            Player.p_shield =
  892. X            Player.p_gold = 0.0;
  893. X            cancelmonster();
  894. X            break;
  895. X
  896. X        case SM_UNGOLIANT:
  897. X            /* (large) poison and take a quickness */
  898. X            mvprintw(Lines++, 0,
  899. X            "%s poisoned you, and took one quik.", Enemyname);
  900. X            Player.p_poison += 5.0;
  901. X            Player.p_quickness -= 1.0;
  902. X            break;
  903. X
  904. X        case SM_JABBERWOCK:
  905. X            /* fly away, and leave either a Jubjub bird or Bonnacon */
  906. X            mvprintw(Lines++, 0,
  907. X            "%s flew away, and left you to contend with one of its friends.",
  908. X            Enemyname);
  909. X            Whichmonster = 55 + (random() > 0.5) ? 22 : 0;
  910. X            longjmp(Fightenv, 0);
  911. X            /*NOTREACHED*/
  912. X
  913. X        case SM_TROLL:
  914. X            /* partially regenerate monster */
  915. X            mvprintw(Lines++, 0,
  916. X            "%s partially regenerated his energy.!", Enemyname);
  917. X            Curmonster.m_energy +=
  918. X            floor((Curmonster.m_o_energy - Curmonster.m_energy) / 2.0);
  919. X            Curmonster.m_strength = Curmonster.m_o_strength;
  920. X            Curmonster.m_melee = Curmonster.m_skirmish = 0.0;
  921. X            Curmonster.m_maxspeed = Curmonster.m_o_speed;
  922. X            break;
  923. X
  924. X        case SM_WRAITH:
  925. X            if (!Player.p_blindness)
  926. X            /* make blind */
  927. X            {
  928. X            mvprintw(Lines++, 0, "%s blinded you!", Enemyname);
  929. X            Player.p_blindness = TRUE;
  930. X            Enemyname = "A monster";
  931. X            }
  932. X            break;
  933. X        }
  934. X        return;
  935. X    }
  936. X
  937. X    /* fall through to here if monster inflicts a normal hit */
  938. X    inflict = random() * Curmonster.m_strength + 0.5;
  939. XSPECIALHIT:
  940. X    mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, inflict);
  941. X
  942. X    if ((Shield -= inflict) < 0)
  943. X    {
  944. X    Player.p_energy += Shield;
  945. X    Shield = 0.0;
  946. X    }
  947. X}
  948. X/* */
  949. X/************************************************************************
  950. X/
  951. X/ FUNCTION NAME: cancelmonster()
  952. X/
  953. X/ FUNCTION: mark current monster as no longer active
  954. X/
  955. X/ AUTHOR: E. A. Estes, 12/4/85
  956. X/
  957. X/ ARGUMENTS: none
  958. X/
  959. X/ RETURN VALUE: none
  960. X/
  961. X/ MODULES CALLED: none
  962. X/
  963. X/ GLOBAL INPUTS: none
  964. X/
  965. X/ GLOBAL OUTPUTS: Curmonster
  966. X/
  967. X/ DESCRIPTION:
  968. X/    Clear current monster's energy, experience, treasure type, and
  969. X/    flock.  This is the same as having the monster run away.
  970. X/
  971. X/************************************************************************/
  972. X
  973. Xcancelmonster()
  974. X{
  975. X    Curmonster.m_energy = 0.0;
  976. X    Curmonster.m_experience = 0.0;
  977. X    Curmonster.m_treasuretype = 0;
  978. X    Curmonster.m_flock = 0.0;
  979. X}
  980. X/* */
  981. X/************************************************************************
  982. X/
  983. X/ FUNCTION NAME: hitmonster()
  984. X/
  985. X/ FUNCTION: inflict damage upon current monster
  986. X/
  987. X/ AUTHOR: E. A. Estes, 12/4/85
  988. X/
  989. X/ ARGUMENTS:
  990. X/    double inflict - damage to inflict upon monster
  991. X/
  992. X/ RETURN VALUE: none
  993. X/
  994. X/ MODULES CALLED: monsthits(), wmove(), strcmp(), waddstr(), mvprintw()
  995. X/
  996. X/ GLOBAL INPUTS: Curmonster, Lines, Player, *stdscr, *Enemyname
  997. X/
  998. X/ GLOBAL OUTPUTS: Curmonster, Lines
  999. X/
  1000. X/ DESCRIPTION:
  1001. X/    Hit monster specified number of times.  Handle when monster dies,
  1002. X/    and a few special monsters.
  1003. X/
  1004. X/************************************************************************/
  1005. X
  1006. Xhitmonster(inflict)
  1007. Xdouble    inflict;
  1008. X{
  1009. X    mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, inflict);
  1010. X    Curmonster.m_energy -= inflict;
  1011. X    if (Curmonster.m_energy > 0.0)
  1012. X    {
  1013. X    if (Curmonster.m_type == SM_DARKLORD || Curmonster.m_type == SM_SHRIEKER)
  1014. X        /* special monster didn't die */
  1015. X        monsthits();
  1016. X    }
  1017. X    else
  1018. X    /* monster died.  print message. */
  1019. X    {
  1020. X    if (Curmonster.m_type == SM_MORGOTH)
  1021. X        mvaddstr(Lines++, 0, "You have defeated Morgoth, but he may return. . .");
  1022. X    else
  1023. X        /* all other types of monsters */
  1024. X        {
  1025. X        mvprintw(Lines++, 0, "You killed it.  Good work, %s.", Player.p_name);
  1026. X
  1027. X        if (Curmonster.m_type == SM_MIMIC
  1028. X        && strcmp(Curmonster.m_name, "A Mimic") != 0
  1029. X        && !Player.p_blindness)
  1030. X        mvaddstr(Lines++, 0, "The body slowly changes into the form of a mimic.");
  1031. X        }
  1032. X    }
  1033. X}
  1034. X/* */
  1035. X/************************************************************************
  1036. X/
  1037. X/ FUNCTION NAME: throwspell()
  1038. X/
  1039. X/ FUNCTION: throw a magic spell
  1040. X/
  1041. X/ AUTHOR: E. A. Estes, 12/4/85
  1042. X/
  1043. X/ ARGUMENTS: none
  1044. X/
  1045. X/ RETURN VALUE: none
  1046. X/
  1047. X/ MODULES CALLED: hitmonster(), cancelmonster(), sqrt(), floor(), wmove(), 
  1048. X/    random(), altercoordinates(), longjmp(), infloat(), waddstr(), mvprintw(), 
  1049. X/    getanswer()
  1050. X/
  1051. X/ GLOBAL INPUTS: Curmonster, Whichmonster, Nomana[], Player, *stdscr, 
  1052. X/    Fightenv[], Illspell[], *Enemyname
  1053. X/
  1054. X/ GLOBAL OUTPUTS: Curmonster, Whichmonster, Shield, Player
  1055. X/
  1056. X/ DESCRIPTION:
  1057. X/    Prompt player and process magic spells.
  1058. X/
  1059. X/************************************************************************/
  1060. X
  1061. Xthrowspell()
  1062. X{
  1063. Xdouble    inflict;    /* damage inflicted */
  1064. Xdouble    dtemp;        /* for dtemporary calculations */
  1065. Xint    ch;        /* input */
  1066. X
  1067. X    mvaddstr(7, 0, "\n\n");        /* clear menu area */
  1068. X
  1069. X    if (Player.p_magiclvl >= ML_ALLORNOTHING)
  1070. X    mvaddstr(7, 0, "1:All or Nothing  ");
  1071. X    if (Player.p_magiclvl >= ML_MAGICBOLT)
  1072. X    addstr("2:Magic Bolt  ");
  1073. X    if (Player.p_magiclvl >= ML_FORCEFIELD)
  1074. X    addstr("3:Force Field  ");
  1075. X    if (Player.p_magiclvl >= ML_XFORM)
  1076. X    addstr("4:Transform  ");
  1077. X    if (Player.p_magiclvl >= ML_INCRMIGHT)
  1078. X    addstr("5:Increase Might\n");
  1079. X    if (Player.p_magiclvl >= ML_INVISIBLE)
  1080. X    mvaddstr(8, 0, "6:Invisibility  ");
  1081. X    if (Player.p_magiclvl >= ML_XPORT)
  1082. X    addstr("7:Transport  ");
  1083. X    if (Player.p_magiclvl >= ML_PARALYZE)
  1084. X    addstr("8:Paralyze  ");
  1085. X    if (Player.p_specialtype >= SC_COUNCIL)
  1086. X    addstr("9:Specify");
  1087. X    mvaddstr(4, 0, "Spell ? ");
  1088. X
  1089. X    ch = getanswer(" ", TRUE);
  1090. X
  1091. X    mvaddstr(7, 0, "\n\n");        /* clear menu area */
  1092. X
  1093. X    if (Curmonster.m_type == SM_MORGOTH && ch != '3')
  1094. X    /* can only throw force field against Morgoth */
  1095. X    ILLSPELL();
  1096. X    else
  1097. X    switch (ch)
  1098. X        {
  1099. X        case '1':   /* all or nothing */
  1100. X        if (random() < 0.25)
  1101. X            /* success */
  1102. X            {
  1103. X            inflict = Curmonster.m_energy * 1.01 + 1.0;
  1104. X
  1105. X            if (Curmonster.m_type == SM_DARKLORD)
  1106. X            /* all or nothing doesn't quite work against D. L. */
  1107. X            inflict *= 0.9;
  1108. X            }
  1109. X        else
  1110. X            /* failure -- monster gets stronger and quicker */
  1111. X            {
  1112. X            Curmonster.m_o_strength = Curmonster.m_strength *= 2.0;
  1113. X            Curmonster.m_maxspeed *= 2.0;
  1114. X            Curmonster.m_o_speed *= 2.0;
  1115. X
  1116. X            /* paralyzed monsters wake up a bit */
  1117. X            Curmonster.m_speed = MAX(1.0, Curmonster.m_speed * 2.0);
  1118. X            }
  1119. X
  1120. X        if (Player.p_mana >= MM_ALLORNOTHING)
  1121. X            /* take a mana if player has one */
  1122. X            Player.p_mana -= MM_ALLORNOTHING;
  1123. X
  1124. X        hitmonster(inflict);
  1125. X        break;
  1126. X
  1127. X        case '2':   /* magic bolt */
  1128. X        if (Player.p_magiclvl < ML_MAGICBOLT)
  1129. X            ILLSPELL();
  1130. X        else
  1131. X            {
  1132. X            do
  1133. X            /* prompt for amount to expend */
  1134. X            {
  1135. X            mvaddstr(4, 0, "How much mana for bolt? ");
  1136. X            dtemp = floor(infloat());
  1137. X            }
  1138. X            while (dtemp < 0.0 || dtemp > Player.p_mana);
  1139. X
  1140. X            Player.p_mana -= dtemp;
  1141. X
  1142. X            if (Curmonster.m_type == SM_DARKLORD)
  1143. X            /* magic bolts don't work against D. L. */
  1144. X            inflict = 0.0;
  1145. X            else
  1146. X            inflict = dtemp * ROLL(15.0, sqrt(Player.p_magiclvl / 3.0 + 1.0));
  1147. X            mvaddstr(5, 0, "Magic Bolt fired!\n");
  1148. X            hitmonster(inflict);
  1149. X            }
  1150. X        break;
  1151. X
  1152. X        case '3':   /* force field */
  1153. X        if (Player.p_magiclvl < ML_FORCEFIELD)
  1154. X            ILLSPELL();
  1155. X        else if (Player.p_mana < MM_FORCEFIELD)
  1156. X            NOMANA();
  1157. X        else
  1158. X            {
  1159. X            Player.p_mana -= MM_FORCEFIELD;
  1160. X            Shield = (Player.p_maxenergy + Player.p_shield) * 4.2 + 45.0;
  1161. X            mvaddstr(5, 0, "Force Field up.\n");
  1162. X            }
  1163. X        break;
  1164. X
  1165. X        case '4':   /* transform */
  1166. X        if (Player.p_magiclvl < ML_XFORM)
  1167. X            ILLSPELL();
  1168. X        else if (Player.p_mana < MM_XFORM)
  1169. X            NOMANA();
  1170. X        else
  1171. X            {
  1172. X            Player.p_mana -= MM_XFORM;
  1173. X            Whichmonster = (int) ROLL(0.0, 100.0);
  1174. X            longjmp(Fightenv, 0);
  1175. X            /*NOTREACHED*/
  1176. X            }
  1177. X        break;
  1178. X
  1179. X        case '5':   /* increase might */
  1180. X        if (Player.p_magiclvl < ML_INCRMIGHT)
  1181. X            ILLSPELL();
  1182. X        else if (Player.p_mana < MM_INCRMIGHT)
  1183. X            NOMANA();
  1184. X        else
  1185. X            {
  1186. X            Player.p_mana -= MM_INCRMIGHT;
  1187. X            Player.p_might +=
  1188. X            (1.2 * (Player.p_strength + Player.p_sword)
  1189. X            + 5.0 - Player.p_might) / 2.0;
  1190. X            mvprintw(5, 0, "New strength:  %.0f\n", Player.p_might);
  1191. X            }
  1192. X        break;
  1193. X
  1194. X        case '6':   /* invisible */
  1195. X        if (Player.p_magiclvl < ML_INVISIBLE)
  1196. X            ILLSPELL();
  1197. X        else if (Player.p_mana < MM_INVISIBLE)
  1198. X            NOMANA();
  1199. X        else
  1200. X            {
  1201. X            Player.p_mana -= MM_INVISIBLE;
  1202. X            Player.p_speed +=
  1203. X            (1.2 * (Player.p_quickness + Player.p_quksilver)
  1204. X            + 5.0 - Player.p_speed) / 2.0;
  1205. X            mvprintw(5, 0, "New quickness:  %.0f\n", Player.p_speed);
  1206. X            }
  1207. X        break;
  1208. X
  1209. X        case '7':   /* transport */
  1210. X        if (Player.p_magiclvl < ML_XPORT)
  1211. X            ILLSPELL();
  1212. X        else if (Player.p_mana < MM_XPORT)
  1213. X            NOMANA();
  1214. X        else
  1215. X            {
  1216. X            Player.p_mana -= MM_XPORT;
  1217. X            if (Player.p_brains + Player.p_magiclvl
  1218. X            < Curmonster.m_experience / 200.0 * random())
  1219. X            {
  1220. X            mvaddstr(5, 0, "Transport backfired!\n");
  1221. X            altercoordinates(0.0, 0.0, A_FAR);
  1222. X            cancelmonster();
  1223. X            }
  1224. X            else
  1225. X            {
  1226. X            mvprintw(5, 0, "%s is transported.\n", Enemyname);
  1227. X            if (random() < 0.3)
  1228. X                /* monster didn't drop its treasure */
  1229. X                Curmonster.m_treasuretype = 0;
  1230. X
  1231. X            Curmonster.m_energy = 0.0;
  1232. X            }
  1233. X            }
  1234. X        break;
  1235. X
  1236. X        case '8':   /* paralyze */
  1237. X        if (Player.p_magiclvl < ML_PARALYZE)
  1238. X            ILLSPELL();
  1239. X        else if (Player.p_mana < MM_PARALYZE)
  1240. X            NOMANA();
  1241. X        else
  1242. X            {
  1243. X            Player.p_mana -= MM_PARALYZE;
  1244. X            if (Player.p_magiclvl >
  1245. X            Curmonster.m_experience / 1000.0 * random())
  1246. X            {
  1247. X            mvprintw(5, 0, "%s is held.\n", Enemyname);
  1248. X            Curmonster.m_speed = -2.0;
  1249. X            }
  1250. X            else
  1251. X            mvaddstr(5, 0, "Monster unaffected.\n");
  1252. X            }
  1253. X        break;
  1254. X
  1255. X        case '9':   /* specify */
  1256. X        if (Player.p_specialtype < SC_COUNCIL)
  1257. X            ILLSPELL();
  1258. X        else if (Player.p_mana < MM_SPECIFY)
  1259. X            NOMANA();
  1260. X        else
  1261. X            {
  1262. X            Player.p_mana -= MM_SPECIFY;
  1263. X            mvaddstr(5, 0, "Which monster do you want [0-99] ? ");
  1264. X            Whichmonster = (int) infloat();
  1265. X            Whichmonster = MAX(0, MIN(99, Whichmonster));
  1266. X            longjmp(Fightenv, 0);
  1267. X            /*NOTREACHED*/
  1268. X            }
  1269. X        break;
  1270. X        }
  1271. X}
  1272. X/* */
  1273. X/************************************************************************
  1274. X/
  1275. X/ FUNCTION NAME: callmonster()
  1276. X/
  1277. X/ FUNCTION: read monster from file, and fill structure
  1278. X/
  1279. X/ AUTHOR: E. A. Estes, 2/25/86
  1280. X/
  1281. X/ ARGUMENTS:
  1282. X/    int which - which monster to call
  1283. X/
  1284. X/ RETURN VALUE: none
  1285. X/
  1286. X/ MODULES CALLED: truncstring(), fread(), fseek(), floor(), random(), 
  1287. X/    strcpy()
  1288. X/
  1289. X/ GLOBAL INPUTS: Curmonster, Circle, Player, *Monstfp
  1290. X/
  1291. X/ GLOBAL OUTPUTS: Curmonster, Player, *Enemyname
  1292. X/
  1293. X/ DESCRIPTION:
  1294. X/    Read specified monster from monster database and fill up
  1295. X/    current monster structure.
  1296. X/    Adjust statistics based upon current size.
  1297. X/    Handle some special monsters.
  1298. X/
  1299. X/************************************************************************/
  1300. X
  1301. Xcallmonster(which)
  1302. Xint    which;
  1303. X{
  1304. Xstruct monster    Othermonster;        /* to find a name for mimics */
  1305. X
  1306. X    which = MIN(which, 99);        /* make sure within range */
  1307. X
  1308. X    /* fill structure */
  1309. X    fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, 0);
  1310. X    fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
  1311. X
  1312. X    /* handle some special monsters */
  1313. X    if (Curmonster.m_type == SM_MODNAR)
  1314. X    {
  1315. X    if (Player.p_specialtype < SC_COUNCIL)
  1316. X        /* randomize some stats */
  1317. X        {
  1318. X        Curmonster.m_strength *= random() + 0.5;
  1319. X        Curmonster.m_brains *= random() + 0.5;
  1320. X        Curmonster.m_speed *= random() + 0.5;
  1321. X        Curmonster.m_energy *= random() + 0.5;
  1322. X        Curmonster.m_experience *= random() + 0.5;
  1323. X        Curmonster.m_treasuretype =
  1324. X        (int) ROLL(0.0, (double) Curmonster.m_treasuretype);
  1325. X        }
  1326. X    else
  1327. X        /* make Modnar into Morgoth */
  1328. X        {
  1329. X        strcpy(Curmonster.m_name, "Morgoth");
  1330. X        Curmonster.m_strength = random() * (Player.p_maxenergy + Player.p_shield) / 1.4
  1331. X        + random() * (Player.p_maxenergy + Player.p_shield) / 1.5;
  1332. X        Curmonster.m_brains = Player.p_brains;
  1333. X        Curmonster.m_energy = Player.p_might * 30.0;
  1334. X        Curmonster.m_type = SM_MORGOTH;
  1335. X        Curmonster.m_speed = Player.p_speed * 1.1
  1336. X        + (Player.p_specialtype == SC_EXVALAR) ? Player.p_speed : 0.0;
  1337. X        Curmonster.m_flock = 0.0;
  1338. X        Curmonster.m_treasuretype = 0;
  1339. X        Curmonster.m_experience = 0.0;
  1340. X        }
  1341. X    }
  1342. X    else if (Curmonster.m_type == SM_MIMIC)
  1343. X    /* pick another name */
  1344. X    {
  1345. X    which = (int) ROLL(0.0, 100.0);
  1346. X    fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, 0);
  1347. X    fread(&Othermonster, SZ_MONSTERSTRUCT, 1, Monstfp);
  1348. X    strcpy(Curmonster.m_name, Othermonster.m_name);
  1349. X    }
  1350. X
  1351. X    truncstring(Curmonster.m_name);
  1352. X
  1353. X    if (Curmonster.m_type != SM_MORGOTH)
  1354. X    /* adjust stats based on which circle player is in */
  1355. X    {
  1356. X    Curmonster.m_strength *= (1.0 + Circle / 2.0);
  1357. X    Curmonster.m_brains *= Circle;
  1358. X    Curmonster.m_speed += Circle * 1.e-9;
  1359. X    Curmonster.m_energy *= Circle;
  1360. X    Curmonster.m_experience *= Circle;
  1361. X    }
  1362. X
  1363. X    if (Player.p_blindness)
  1364. X    /* cannot see monster if blind */
  1365. X    Enemyname = "A monster";
  1366. X    else
  1367. X    Enemyname = Curmonster.m_name;
  1368. X
  1369. X    if (Player.p_speed <= 0.0)
  1370. X    /* make Player.p_speed positive */
  1371. X    {
  1372. X    Curmonster.m_speed += -Player.p_speed;
  1373. X    Player.p_speed = 1.0;
  1374. X    }
  1375. X
  1376. X    /* fill up the rest of the structure */
  1377. X    Curmonster.m_o_strength = Curmonster.m_strength;
  1378. X    Curmonster.m_o_speed = Curmonster.m_maxspeed = Curmonster.m_speed;
  1379. X    Curmonster.m_o_energy = Curmonster.m_energy;
  1380. X    Curmonster.m_melee = Curmonster.m_skirmish = 0.0;
  1381. X}
  1382. X/* */
  1383. X/************************************************************************
  1384. X/
  1385. X/ FUNCTION NAME: awardtreasure()
  1386. X/
  1387. X/ FUNCTION: select a treasure
  1388. X/
  1389. X/ AUTHOR: E. A. Estes, 12/4/85
  1390. X/
  1391. X/ ARGUMENTS: none
  1392. X/
  1393. X/ RETURN VALUE: none
  1394. X/
  1395. X/ MODULES CALLED: pickmonster(), collecttaxes(), more(), cursedtreasure(), 
  1396. X/    floor(), wmove(), random(), sscanf(), printw(), altercoordinates(), 
  1397. X/    longjmp(), infloat(), waddstr(), getanswer(), getstring(), wclrtobot()
  1398. X/
  1399. X/ GLOBAL INPUTS: Somebetter[], Curmonster, Whichmonster, Circle, Player, 
  1400. X/    *stdscr, Databuf[], *Statptr, Fightenv[]
  1401. X/
  1402. X/ GLOBAL OUTPUTS: Whichmonster, Shield, Player
  1403. X/
  1404. X/ DESCRIPTION:
  1405. X/    Roll up a treasure based upon monster type and size, and
  1406. X/    certain player statistics.
  1407. X/    Handle cursed treasure.
  1408. X/
  1409. X/************************************************************************/
  1410. X
  1411. Xawardtreasure()
  1412. X{
  1413. Xregister int    whichtreasure;        /* calculated treasure to grant */
  1414. Xint    temp;                /* temporary */
  1415. Xint    ch;                /* input */
  1416. Xdouble    treasuretype;            /* monster's treasure type */
  1417. Xdouble    gold = 0.0;            /* gold awarded */
  1418. Xdouble    gems = 0.0;            /* gems awarded */
  1419. Xdouble    dtemp;                /* for temporary calculations */
  1420. X
  1421. X    whichtreasure = (int) ROLL(1.0, 3.0);    /* pick a treasure */
  1422. X    treasuretype = (double) Curmonster.m_treasuretype;
  1423. X
  1424. X    move(4, 0);
  1425. X    clrtobot();
  1426. X    move(6, 0);
  1427. X
  1428. X    if (random() > 0.65)
  1429. X    /* gold and gems */
  1430. X    {
  1431. X    if (Curmonster.m_treasuretype > 7)
  1432. X        /* gems */
  1433. X        {
  1434. X        gems = ROLL(1.0, (treasuretype - 7.0)
  1435. X        * (treasuretype - 7.0) * (Circle - 1.0) / 4.0);
  1436. X        printw("You have discovered %.0f gems!", gems);
  1437. X        }
  1438. X    else
  1439. X        /* gold */
  1440. X        {
  1441. X        gold = ROLL(treasuretype * 10.0, treasuretype
  1442. X        * treasuretype * 10.0 * (Circle - 1.0));
  1443. X        printw("You have found %.0f gold pieces.", gold);
  1444. X        }
  1445. X
  1446. X    addstr("  Do you want to pick them up ? ");
  1447. X    ch = getanswer("NY", FALSE);
  1448. X    addstr("\n\n");
  1449. X
  1450. X    if (ch == 'Y')
  1451. X        if (random() < treasuretype / 35.0 + 0.04)
  1452. X        /* cursed */
  1453. X        {
  1454. X        addstr("They were cursed!\n");
  1455. X        cursedtreasure();
  1456. X        }
  1457. X        else
  1458. X        collecttaxes(gold, gems);
  1459. X
  1460. X    return;
  1461. X    }
  1462. X    else   
  1463. X    /* other treasures */
  1464. X    {
  1465. X    addstr("You have found some treasure.  Do you want to inspect it ? ");
  1466. X    ch = getanswer("NY", FALSE);
  1467. X    addstr("\n\n");
  1468. X
  1469. X    if (ch != 'Y')
  1470. X        return;
  1471. X    else
  1472. X        if (random() < 0.08 && Curmonster.m_treasuretype != 4)
  1473. X        {
  1474. X        addstr("It was cursed!\n");
  1475. X        cursedtreasure();
  1476. X        return;
  1477. X        }
  1478. X        else
  1479. X        switch (Curmonster.m_treasuretype)
  1480. X            {
  1481. X            case 1:    /* treasure type 1 */
  1482. X            switch (whichtreasure)
  1483. X                {
  1484. X                case 1:
  1485. X                addstr("You've discovered a power booster!\n");
  1486. X                Player.p_mana += ROLL(Circle * 4.0, Circle * 30.0);
  1487. X                break;
  1488. X
  1489. X                case 2:
  1490. X                addstr("You have encountered a druid.\n");
  1491. X                Player.p_experience +=
  1492. X                    ROLL(0.0, 2000.0 + Circle * 400.0);
  1493. X                break;
  1494. X
  1495. X                case 3:
  1496. X                addstr("You have found a holy orb.\n");
  1497. X                Player.p_sin = MAX(0.0, Player.p_sin - 0.25);
  1498. X                break;
  1499. X                }
  1500. X            break;
  1501. X            /* end treasure type 1 */
  1502. X
  1503. X            case 2:    /* treasure type 2 */
  1504. X            switch (whichtreasure)
  1505. X                {
  1506. X                case 1:
  1507. X                addstr("You have found an amulet.\n");
  1508. X                ++Player.p_amulets;
  1509. X                break;
  1510. X
  1511. X                case 2:
  1512. X                addstr("You've found some holy water!\n");
  1513. X                ++Player.p_holywater;
  1514. X                break;
  1515. X
  1516. X                case 3:
  1517. X                addstr("You've met a hermit!\n");
  1518. X                Player.p_sin *= 0.75;
  1519. X                Player.p_mana += 12.0 * Circle;
  1520. X                break;
  1521. X                }
  1522. X            break;
  1523. X            /* end treasure type 2 */
  1524. X
  1525. X            case 3:    /* treasure type 3 */
  1526. X            switch (whichtreasure)
  1527. X                {
  1528. X                case 1:
  1529. X                dtemp = ROLL(7.0, 30.0 + Circle / 10.0);
  1530. X                printw("You've found a +%.0f shield!\n", dtemp);
  1531. X                if (dtemp >= Player.p_shield)
  1532. X                    Player.p_shield = dtemp;
  1533. X                else
  1534. X                    SOMEBETTER();
  1535. X                break;
  1536. X
  1537. X                case 2:
  1538. X                addstr("You have rescued a virgin.  Will you be honorable ? ");
  1539. X                ch = getanswer("NY", FALSE);
  1540. X                addstr("\n\n");
  1541. X                if (ch == 'Y')
  1542. X                    Player.p_virgin = TRUE;
  1543. X                else
  1544. X                    {
  1545. X                    Player.p_experience += 2000.0 * Circle;
  1546. X                    ++Player.p_sin;
  1547. X                    }
  1548. X                break;
  1549. X
  1550. X                case 3:
  1551. X                addstr("You've discovered some athelas!\n");
  1552. X                --Player.p_poison;
  1553. X                break;
  1554. X                }
  1555. X            break;
  1556. X            /* end treasure type 3 */
  1557. X
  1558. X            case 4:    /* treasure type 4 */
  1559. X            addstr("You've found a scroll.  Will you read it ? ");
  1560. X            ch = getanswer("NY", FALSE);
  1561. X            addstr("\n\n");
  1562. X
  1563. X            if (ch == 'Y')
  1564. X                switch ((int) ROLL(1, 6))
  1565. X                {
  1566. X                case 1:
  1567. X                    addstr("It throws up a shield for you next monster.\n");
  1568. X                    getyx(stdscr, whichtreasure, ch);
  1569. X                    more(whichtreasure);
  1570. X                    Shield =
  1571. X                    (Player.p_maxenergy + Player.p_energy) * 5.5 + Circle * 50.0;
  1572. X                    Whichmonster = pickmonster();
  1573. X                    longjmp(Fightenv, 0);
  1574. X                    /*NOTREACHED*/
  1575. X
  1576. X                case 2:
  1577. X                    addstr("It makes you invisible for you next monster.\n");
  1578. X                    getyx(stdscr, whichtreasure, ch);
  1579. X                    more(whichtreasure);
  1580. X                    Player.p_speed = 1e6;
  1581. X                    Whichmonster = pickmonster();
  1582. X                    longjmp(Fightenv, 0);
  1583. X                    /*NOTREACHED*/
  1584. X
  1585. X                case 3:
  1586. X                    addstr("It increases your strength ten fold to fight your next monster.\n");
  1587. X                    getyx(stdscr, whichtreasure, ch);
  1588. X                    more(whichtreasure);
  1589. X                    Player.p_might *= 10.0;
  1590. X                    Whichmonster = pickmonster();
  1591. X                    longjmp(Fightenv, 0);
  1592. X                    /*NOTREACHED*/
  1593. X
  1594. X                case 4:
  1595. X                    addstr("It is a general knowledge scroll.\n");
  1596. X                    Player.p_brains += ROLL(2.0, Circle);
  1597. X                    Player.p_magiclvl += ROLL(1.0, Circle / 2.0);
  1598. X                    break;
  1599. X
  1600. X                case 5:
  1601. X                    addstr("It tells you how to pick your next monster.\n");
  1602. X                    addstr("Which monster do you want [0-99] ? ");
  1603. X                    Whichmonster = (int) infloat();
  1604. X                    Whichmonster = MIN(99, MAX(0, Whichmonster));
  1605. X                    longjmp(Fightenv, 0);
  1606. X
  1607. X                case 6:
  1608. X                    addstr("It was cursed!\n");
  1609. X                    cursedtreasure();
  1610. X                    break;
  1611. X                }
  1612. X                break;
  1613. X            /* end treasure type 4 */
  1614. X
  1615. X            case 5:    /* treasure type 5 */
  1616. X            switch (whichtreasure)
  1617. X                {
  1618. X                case 1:
  1619. X                dtemp = ROLL(Circle / 4.0 + 5.0, Circle / 2.0 + 9.0);
  1620. X                printw("You've discovered a +%.0f dagger.\n", dtemp);
  1621. X                if (dtemp >= Player.p_sword)
  1622. X                    Player.p_sword = dtemp;
  1623. X                else
  1624. X                    SOMEBETTER();
  1625. X                break;
  1626. X
  1627. X                case 2:
  1628. X                dtemp = ROLL(7.5 + Circle * 3.0, Circle * 2.0 + 160.0);
  1629. X                printw("You have found some +%.0f armour!\n", dtemp);
  1630. X                if (dtemp >= Player.p_shield)
  1631. X                    Player.p_shield = dtemp;
  1632. X                else
  1633. X                    SOMEBETTER();
  1634. X                break;
  1635. X
  1636. X                case 3:
  1637. X                addstr("You've found a tablet.\n");
  1638. X                Player.p_brains += 4.5 * Circle;
  1639. X                break;
  1640. X                }
  1641. X            break;
  1642. X            /* end treasure type 5 */
  1643. X
  1644. X            case 6:    /* treasure type 6 */
  1645. X            switch (whichtreasure)
  1646. X                {
  1647. X                case 1:
  1648. X                addstr("You've found a priest.\n");
  1649. X                Player.p_energy = Player.p_maxenergy + Player.p_shield;
  1650. X                Player.p_sin /= 2.0;
  1651. X                Player.p_mana += 24.0 * Circle;
  1652. X                Player.p_brains += Circle;
  1653. X                break;
  1654. X
  1655. X                case 2:
  1656. X                addstr("You have come upon Robin Hood!\n");
  1657. X                Player.p_shield += Circle * 2.0;
  1658. X                Player.p_strength += Circle / 2.5 + 1.0;
  1659. X                break;
  1660. X
  1661. X                case 3:
  1662. X                dtemp = ROLL(2.0 + Circle / 4.0, Circle / 1.2 + 10.0);
  1663. X                printw("You have found a +%.0f axe!\n", dtemp);
  1664. X                if (dtemp >= Player.p_sword)
  1665. X                    Player.p_sword = dtemp;
  1666. X                else
  1667. X                    SOMEBETTER();
  1668. X                break;
  1669. X                }
  1670. X            break;
  1671. X            /* end treasure type 6 */
  1672. X
  1673. X            case 7:    /* treasure type 7 */
  1674. X            switch (whichtreasure)
  1675. X                {
  1676. X                case 1:
  1677. X                addstr("You've discovered a charm!\n");
  1678. X                ++Player.p_charms;
  1679. X                break;
  1680. X
  1681. X                case 2:
  1682. X                addstr("You have encountered Merlyn!\n");
  1683. X                Player.p_brains += Circle + 5.0;
  1684. X                Player.p_magiclvl += Circle / 3.0 + 5.0;
  1685. X                Player.p_mana += Circle * 10.0;
  1686. X                break;
  1687. X
  1688. X                case 3:
  1689. X                dtemp = ROLL(5.0 + Circle / 3.0, Circle / 1.5 + 20.0);
  1690. X                printw("You have found a +%.0f war hammer!\n", dtemp);
  1691. X                if (dtemp >= Player.p_sword)
  1692. X                    Player.p_sword = dtemp;
  1693. X                else
  1694. X                    SOMEBETTER();
  1695. X                break;
  1696. X                }
  1697. X            break;
  1698. X            /* end treasure type 7 */
  1699. X
  1700. X            case 8:    /* treasure type 8 */
  1701. X            switch (whichtreasure)
  1702. X                {
  1703. X                case 1:
  1704. X                addstr("You have found a healing potion.\n");
  1705. X                Player.p_poison = MIN(-2.0, Player.p_poison - 2.0);
  1706. X                break;
  1707. X
  1708. X                case 2:
  1709. X                addstr("You have discovered a transporter.  Do you wish to go anywhere ? ");
  1710. X                ch = getanswer("NY", FALSE);
  1711. X                addstr("\n\n");
  1712. X                if (ch == 'Y')
  1713. X                    {
  1714. X                    double x, y;
  1715. X
  1716. X                    addstr("X Y Coordinates ? ");
  1717. X                    getstring(Databuf, SZ_DATABUF);
  1718. X                    sscanf(Databuf, "%F %F", &x, &y);
  1719. X                    altercoordinates(x, y, A_FORCED);
  1720. X                    }
  1721. X                break;
  1722. X
  1723. X                case 3:
  1724. X                dtemp = ROLL(10.0 + Circle / 1.2, Circle * 3.0 + 30.0);
  1725. X                printw("You've found a +%.0f sword!\n", dtemp);
  1726. X                if (dtemp >= Player.p_sword)
  1727. X                    Player.p_sword = dtemp;
  1728. X                else
  1729. X                    SOMEBETTER();
  1730. X                break;
  1731. X                }
  1732. X            break;
  1733. X            /* end treasure type 8 */
  1734. X
  1735. X            case 10:
  1736. X            case 11:
  1737. X            case 12:
  1738. X            case 13:    /* treasure types 10 - 13 */
  1739. X            if (random() < 0.33)
  1740. X                {
  1741. X                if (Curmonster.m_treasuretype == 10)
  1742. X                {
  1743. X                addstr("You've found a pair of elven boots!\n");
  1744. X                Player.p_quickness += 2.0;
  1745. X                break;
  1746. X                }
  1747. X                else if (Curmonster.m_treasuretype == 11
  1748. X                && !Player.p_palantir)
  1749. X                {
  1750. X                addstr("You've acquired Saruman's palantir.\n");
  1751. X                Player.p_palantir = TRUE;
  1752. X                break;
  1753. X                }
  1754. X                else if (Player.p_ring.ring_type == R_NONE
  1755. X                && Player.p_specialtype < SC_COUNCIL
  1756. X                && (Curmonster.m_treasuretype == 12
  1757. X                || Curmonster.m_treasuretype == 13))
  1758. X                /* roll up a ring */
  1759. X                {
  1760. X                if (random() < 0.8)
  1761. X                    /* regular rings */
  1762. X                    {
  1763. X                    if (Curmonster.m_treasuretype == 12)
  1764. X                    {
  1765. X                    whichtreasure = R_NAZREG;
  1766. X                    temp = 35;
  1767. X                    }
  1768. X                    else
  1769. X                    {
  1770. X                    whichtreasure = R_DLREG;
  1771. X                    temp = 0;
  1772. X                    }
  1773. X                    }
  1774. X                else
  1775. X                    /* bad rings */
  1776. X                    {
  1777. X                    whichtreasure = R_BAD;
  1778. X                    temp = 15 + Statptr->c_ringduration + (int) ROLL(0,5);
  1779. X                    }
  1780. X
  1781. X                addstr("You've discovered a ring.  Will you pick it up ? ");
  1782. X                ch = getanswer("NY", FALSE);
  1783. X                addstr("\n\n");
  1784. X
  1785. X                if (ch == 'Y')
  1786. X                    {
  1787. X                    Player.p_ring.ring_type = whichtreasure;
  1788. X                    Player.p_ring.ring_duration = temp;
  1789. X                    }
  1790. X
  1791. X                break;
  1792. X                }
  1793. X                }
  1794. X            /* end treasure types 10 - 13 */
  1795. X            /* fall through to treasure type 9 if no treasure from above */
  1796. X
  1797. X            case 9:    /* treasure type 9 */
  1798. X                switch (whichtreasure)
  1799. X                {
  1800. X                case 1:
  1801. X                    if (Player.p_level <= 1000.0
  1802. X                    && Player.p_crowns <= 3
  1803. X                    && Player.p_level >= 10.0)
  1804. X                    {
  1805. X                    addstr("You have found a golden crown!\n");
  1806. X                    ++Player.p_crowns;
  1807. X                    break;
  1808. X                    }
  1809. X                    /* fall through otherwise */
  1810. X
  1811. X                case 2:
  1812. X                    addstr("You've been blessed!\n");
  1813. X                    Player.p_blessing = TRUE;
  1814. X                    Player.p_sin /= 3.0;
  1815. X                    Player.p_energy = Player.p_maxenergy + Player.p_shield;
  1816. X                    Player.p_mana += 100.0 * Circle;
  1817. X                    break;
  1818. X
  1819. X                case 3:
  1820. X                    dtemp = ROLL(1.0, Circle / 5.0 + 5.0);
  1821. X                    dtemp = MIN(dtemp, 99.0);
  1822. X                    printw("You have discovered some +%.0f quicksilver!\n",dtemp);
  1823. X                    if (dtemp >= Player.p_quksilver)
  1824. X                    Player.p_quksilver = dtemp;
  1825. X                    else
  1826. X                    SOMEBETTER();
  1827. X                    break;
  1828. X                }
  1829. X                break;
  1830. X            /* end treasure type 9 */
  1831. X            }
  1832. X    }
  1833. X}
  1834. X/* */
  1835. X/************************************************************************
  1836. X/
  1837. X/ FUNCTION NAME: cursedtreasure()
  1838. X/
  1839. X/ FUNCTION: take care of cursed treasure
  1840. X/
  1841. X/ AUTHOR: E. A. Estes, 12/4/85
  1842. X/
  1843. X/ ARGUMENTS: none
  1844. X/
  1845. X/ RETURN VALUE: none
  1846. X/
  1847. X/ MODULES CALLED: waddstr()
  1848. X/
  1849. X/ GLOBAL INPUTS: Player, *stdscr
  1850. X/
  1851. X/ GLOBAL OUTPUTS: Player
  1852. X/
  1853. X/ DESCRIPTION:
  1854. X/    Handle cursed treasure.  Look for amulets and charms to save
  1855. X/    the player from the curse.
  1856. X/
  1857. X/************************************************************************/
  1858. X
  1859. Xcursedtreasure()
  1860. X{
  1861. X    if (Player.p_charms > 0)
  1862. X    {
  1863. X    addstr("But your charm saved you!\n");
  1864. X    --Player.p_charms;
  1865. X    }
  1866. X    else if (Player.p_amulets > 0)
  1867. X    {
  1868. X    addstr("But your amulet saved you!\n");
  1869. X    --Player.p_amulets;
  1870. X    }
  1871. X    else
  1872. X    {
  1873. X    Player.p_energy = (Player.p_maxenergy + Player.p_shield) / 10.0;
  1874. X    Player.p_poison += 0.25;
  1875. X    }
  1876. X}
  1877. X/* */
  1878. X/************************************************************************
  1879. X/
  1880. X/ FUNCTION NAME: scramblestats()
  1881. X/
  1882. X/ FUNCTION: scramble some selected statistics
  1883. X/
  1884. X/ AUTHOR: E. A. Estes, 12/4/85
  1885. X/
  1886. X/ ARGUMENTS: none
  1887. X/
  1888. X/ RETURN VALUE: none
  1889. X/
  1890. X/ MODULES CALLED: floor(), random()
  1891. X/
  1892. X/ GLOBAL INPUTS: Player
  1893. X/
  1894. X/ GLOBAL OUTPUTS: Player
  1895. X/
  1896. X/ DESCRIPTION:
  1897. X/    Swap a few player statistics randomly.
  1898. X/
  1899. X/************************************************************************/
  1900. X
  1901. Xscramblestats()
  1902. X{
  1903. Xdouble    dbuf[6];        /* to put statistic in */
  1904. Xdouble    dtemp1, dtemp2;        /* for swapping values */
  1905. Xregister int    first, second;    /* indices for swapping */
  1906. Xregister double  *dptr;        /* pointer for filling and emptying buf[] */
  1907. X
  1908. X    /* fill buffer */
  1909. X    dptr = &dbuf[0];
  1910. X    *dptr++ = Player.p_strength;
  1911. X    *dptr++ = Player.p_mana;
  1912. X    *dptr++ = Player.p_brains;
  1913. X    *dptr++ = Player.p_magiclvl;
  1914. X    *dptr++ = Player.p_energy;
  1915. X    *dptr = Player.p_sin;
  1916. X
  1917. X    /* pick values to swap */
  1918. X    first = (int) ROLL(0, 5);
  1919. X    second = (int) ROLL(0, 5);
  1920. X
  1921. X    /* swap values */
  1922. X    dptr = &dbuf[0];
  1923. X    dtemp1 = dptr[first];
  1924. X    /* this expression is split to prevent a compiler loop on some compilers */
  1925. X    dtemp2 = dptr[second];
  1926. X    dptr[first] = dtemp2;
  1927. X    dptr[second] = dtemp1;
  1928. X
  1929. X    /* empty buffer */
  1930. X    Player.p_strength = *dptr++;
  1931. X    Player.p_mana = *dptr++;
  1932. X    Player.p_brains = *dptr++;
  1933. X    Player.p_magiclvl = *dptr++;
  1934. X    Player.p_energy = *dptr++;
  1935. X    Player.p_sin = *dptr;
  1936. X}
  1937. !EOR!
  1938. echo x - convert.c
  1939. sed 's/^X//' > convert.c << '!EOR!'
  1940. X/*
  1941. X *    Convert Phantasia 3.3.1 and 3.3.1+ characs file format to 3.3.2
  1942. X *
  1943. X */
  1944. X
  1945. X#include "include.h"
  1946. X#include "oldplayer.h"
  1947. X
  1948. Xstruct oldplayer    Oldplayer;        /* old format structure */
  1949. Xstruct player    Newplayer;            /* new format structure */
  1950. X
  1951. Xchar    Oldpfile[] = DEST/characs";        /* old format file */
  1952. Xchar    Newpfile[] = DEST/newcharacs";        /* new format file */
  1953. X
  1954. X/************************************************************************
  1955. X/
  1956. X/ FUNCTION NAME: main()
  1957. X/
  1958. X/ FUNCTION: convert old Phantasia player file to new format
  1959. X/
  1960. X/ AUTHOR: C. Robertson, 9/1/85  E. A. Estes, 3/12/86
  1961. X/
  1962. X/ ARGUMENTS: none
  1963. X/
  1964. X/ RETURN VALUE: none
  1965. X/
  1966. X/ MODULES CALLED: time(), exit(), fread(), fopen(), srand(), floor(), 
  1967. X/    random(), strcmp(), fwrite(), strcpy(), fclose(), fprintf()
  1968. X/
  1969. X/ GLOBAL INPUTS: _iob[], Oldplayer, Newplayer
  1970. X/
  1971. X/ GLOBAL OUTPUTS: Oldplayer, Newplayer
  1972. X/
  1973. X/ DESCRIPTION:
  1974. X/    Read in old player structures and write out to new file in
  1975. X/    new format.
  1976. X/    Old player file is unmodified.
  1977. X/    New file is "DEST/newcharacs".
  1978. X/    #define PHANTPLUS to convert from 3.3.1+.
  1979. X/
  1980. X/************************************************************************/
  1981. X
  1982. Xmain()
  1983. X{
  1984. XFILE    *oldcharac, *newcharac;        /* to open old and new files */
  1985. X
  1986. X    if ((oldcharac = fopen(Oldpfile, "r")) == NULL)
  1987. X    {
  1988. X    fprintf(stderr, "Cannot open original character file!\n");
  1989. X    exit(1);
  1990. X    }
  1991. X
  1992. X    if ((newcharac = fopen(Newpfile, "w")) == NULL)
  1993. X    {
  1994. X    fprintf(stderr, "Cannot create new character file!\n");
  1995. X    exit(1);
  1996. X    }
  1997. X
  1998. X    srand((unsigned) time((long *) NULL));    /* prime random numbers */
  1999. X
  2000. X    while (fread((char *) &Oldplayer, sizeof(struct oldplayer), 1, oldcharac) == 1)
  2001. X    /* read and convert old structures into new */
  2002. X    {
  2003. X    Newplayer.p_experience = Oldplayer.o_experience;
  2004. X    Newplayer.p_level = (double) Oldplayer.o_level;
  2005. X    Newplayer.p_strength =  Oldplayer.o_strength;
  2006. X    Newplayer.p_sword =  Oldplayer.o_sword;
  2007. X    Newplayer.p_might =  0.0;        /* game will calculate */
  2008. X    Newplayer.p_energy =  Oldplayer.o_energy;
  2009. X    Newplayer.p_maxenergy =  Oldplayer.o_maxenergy;
  2010. X    Newplayer.p_shield =  Oldplayer.o_shield;
  2011. X    Newplayer.p_quickness = (double) Oldplayer.o_quickness;
  2012. X    Newplayer.p_quksilver = (double) Oldplayer.o_quksilver;
  2013. X    Newplayer.p_speed = 0.0;        /* game will calculate */
  2014. X    Newplayer.p_magiclvl = Oldplayer.o_magiclvl;
  2015. X    Newplayer.p_mana = Oldplayer.o_mana;
  2016. X    Newplayer.p_brains = Oldplayer.o_brains;
  2017. X    Newplayer.p_poison = Oldplayer.o_poison;
  2018. X    Newplayer.p_gold = Oldplayer.o_gold;
  2019. X    Newplayer.p_gems = Oldplayer.o_gems;
  2020. X    Newplayer.p_sin = Oldplayer.o_sin;
  2021. X    Newplayer.p_x = Oldplayer.o_x;
  2022. X    Newplayer.p_y = Oldplayer.o_y;
  2023. X    Newplayer.p_1scratch = Oldplayer.o_1scratch;
  2024. X    Newplayer.p_2scratch = Oldplayer.o_2scratch;
  2025. X
  2026. X    Newplayer.p_ring.ring_type = Oldplayer.o_ring.ring_type;
  2027. X    Newplayer.p_ring.ring_duration = Oldplayer.o_ring.ring_duration;
  2028. X    Newplayer.p_ring.ring_inuse = FALSE;
  2029. X
  2030. X    Newplayer.p_age = (long) Oldplayer.o_degenerated * N_AGE;
  2031. X
  2032. X    Newplayer.p_degenerated = Oldplayer.o_degenerated + 1;
  2033. X
  2034. X    /* convert character type into character type and special type */
  2035. X
  2036. X    if (Oldplayer.o_type < 0)
  2037. X        /* player with crown */
  2038. X        Oldplayer.o_type = -Oldplayer.o_type;
  2039. X
  2040. X    if (Oldplayer.o_type == 99)
  2041. X        /* valar */
  2042. X        {
  2043. X        Newplayer.p_specialtype = SC_VALAR;
  2044. X        Newplayer.p_type = (short) ROLL(C_MAGIC, C_EXPER - C_MAGIC + 1);
  2045. X        Newplayer.p_lives = Oldplayer.o_ring.ring_duration;
  2046. X        }
  2047. X    else if (Oldplayer.o_type == 90)
  2048. X        /* ex-valar */
  2049. X        {
  2050. X        Newplayer.p_specialtype = SC_EXVALAR;
  2051. X        Newplayer.p_type = (short) ROLL(C_MAGIC, C_EXPER - C_MAGIC + 1);
  2052. X        Newplayer.p_lives = 0;
  2053. X        }
  2054. X    else if (Oldplayer.o_type > 20)
  2055. X        /* council of wise */
  2056. X        {
  2057. X        Newplayer.p_specialtype = SC_COUNCIL;
  2058. X        Newplayer.p_type = Oldplayer.o_type - 20;
  2059. X        Newplayer.p_lives = Oldplayer.o_ring.ring_duration;
  2060. X        }
  2061. X    else if (Oldplayer.o_type > 10)
  2062. X        /* king */
  2063. X        {
  2064. X        Newplayer.p_specialtype = SC_KING;
  2065. X        Newplayer.p_type = Oldplayer.o_type - 10;
  2066. X        Newplayer.p_lives = 0;
  2067. X        }
  2068. X    else
  2069. X        /* normal player */
  2070. X        {
  2071. X        Newplayer.p_specialtype = SC_NONE;
  2072. X        Newplayer.p_type = Oldplayer.o_type;
  2073. X        Newplayer.p_lives = 0;
  2074. X        }
  2075. X
  2076. X    Newplayer.p_lives = 0;
  2077. X    Newplayer.p_crowns = Oldplayer.o_crowns;
  2078. X    Newplayer.p_charms = Oldplayer.o_charms;
  2079. X    Newplayer.p_amulets = Oldplayer.o_amulets;
  2080. X    Newplayer.p_holywater = Oldplayer.o_holywater;
  2081. X    Newplayer.p_lastused = Oldplayer.o_lastused;
  2082. X
  2083. X    /* convert status and name into status */
  2084. X
  2085. X    Newplayer.p_status = Oldplayer.o_status + S_OFF;
  2086. X    if (strcmp(Oldplayer.m_name, "<null>") == 0)
  2087. X        /* unused recored */
  2088. X        Newplayer.p_status = S_NOTUSED;
  2089. X    if (Oldplayer.o_quickness < 0)
  2090. X        /* hung up player */
  2091. X        {
  2092. X        Newplayer.p_quickness = (double) Oldplayer.o_tampered;
  2093. X        Oldplayer.o_tampered = T_OFF;
  2094. X        Newplayer.p_status = S_HUNGUP;
  2095. X        }
  2096. X
  2097. X    Newplayer.p_tampered = Oldplayer.o_tampered + T_OFF;
  2098. X    Newplayer.p_istat = I_OFF;
  2099. X
  2100. X    Newplayer.p_palantir = Oldplayer.o_palantir;
  2101. X    Newplayer.p_blessing = Oldplayer.o_blessing;
  2102. X    Newplayer.p_virgin = Oldplayer.o_virgin;
  2103. X    Newplayer.p_blindness = Oldplayer.o_blindness;
  2104. X
  2105. X    strcpy(Newplayer.p_name, Oldplayer.o_name);
  2106. X    strcpy(Newplayer.p_password, Oldplayer.o_password);
  2107. X    strcpy(Newplayer.p_login, Oldplayer.o_login);
  2108. X
  2109. X    /* write new structure */
  2110. X    fwrite((char *) &Newplayer, sizeof(Newplayer), 1, newcharac);
  2111. X    }
  2112. X
  2113. X    fclose(oldcharac);        /* close files */
  2114. X    fclose(newcharac);
  2115. X
  2116. X    exit(0);
  2117. X}
  2118. X/* */
  2119. X/************************************************************************
  2120. X/
  2121. X/ FUNCTION NAME: random()
  2122. X/
  2123. X/ FUNCTION: return a random number between 0.0 < 1.0
  2124. X/
  2125. X/ AUTHOR: E. A. Estes, 2/7/86
  2126. X/
  2127. X/ ARGUMENTS: none
  2128. X/
  2129. X/ RETURN VALUE: random number
  2130. X/
  2131. X/ MODULES CALLED: rand()
  2132. X/
  2133. X/ GLOBAL INPUTS: none
  2134. X/
  2135. X/ GLOBAL OUTPUTS: none
  2136. X/
  2137. X/ DESCRIPTION:
  2138. X/    Return a random number.
  2139. X/
  2140. X/************************************************************************/
  2141. X
  2142. Xdouble
  2143. Xrandom()
  2144. X{
  2145. X    if (sizeof(int) != 2)
  2146. X    return((double) (rand() & 0x7fff) / 32768.0);
  2147. X    else
  2148. X    return((double) rand() / 32768.0);
  2149. X}
  2150. !EOR!
  2151.  
  2152.  
  2153.